<template>
    <div class="Uploader file-upload-wrap" :class="fileList.length > 0 ?'show':''" :style="{width:panelHideList?'50px': '735px'}">
        <uploader
                ref="uploader"
                inputId="uploader-input"
                name="up-file"
                multiple="true"
                directory="true"
                :options="options"
                :autoStart="false"
                @file-added="onFileAdded"
                @file-success="onFileSuccess"
                @file-progress="onFileProgress"
                @file-complete="onFileComplete"
                @file-error="onFileError"
                :file-status-text="statusText"
                @dragleave="hideDrag"
                @dragover="hideDrag"
                @dragenter="showDrag">

            <div class="file-upload-view show-upload-view" slot-scope="props" :style="{backgroundColor: panelHideList ? 'transparent' : '#fff',border: panelHideList ? 'none' : '1px solid #f0f0f0', boxShadow: panelHideList ? 'none' : '-4px -4px 13px 0 rgba(213, 217, 220, 0.33)'}">

                <div class="progress-wrapper" v-show="panelHideList" @click="panelHideList=!panelHideList">
                    <b class="progress">
                        <svg width="50px" height="50px" viewBox="0 0 36 36" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><circle id="Combined-Shape" :stroke="UploadedSize == AllFileSize && AllFileSize != 0 ? '#01BD88' : '#00A4FF'" fill="transparent" stroke-width="2" cx="18" cy="18" r="17" :style="{
                        strokeDashoffset:1000 - (AllFileSize == 0 ? 0 : (106 / 100) * (UploadedSize / AllFileSize) * 100)

                        }"></circle></svg>
                    </b>
                    <button class="btn btn-icon"> {{ UploadedSize == AllFileSize ? '完成' : Math.floor(UploadedSize / AllFileSize * 100 )+'%'  }}</button>
                </div>
                <div v-show="!panelHideList">
                    <div class="upload-view-header dp-f">
                        <div class="head-completed dp-f">
                            <div class="success">
                                <i class="ivu-icon ivu-icon-ios-checkmark-outline" style="font-size: 20px; color: rgb(79, 189, 18);"></i>
                                <span>上传成功1个</span>
                            </div>
                        </div>
                        <div class="upload-close dp-f">
                            <div class="min">
                                <i class="icon-window-fold" @click="panelHideList=!panelHideList"></i>
                            </div>
                            <div class="close">
                                <i class="icon-all-close"></i>
                            </div>
                        </div>
                    </div>
                    <div class="upload-view-title">
                        <div class="title-file-name"> 文件(夹)名</div>
                        <div class="title-file-size"> 大小</div>
                        <div class="title-target-dir"> 上传目录</div>
                        <div class="title-upload-status" style="width: 138px;"> 状态</div>
                        <div class="title-upload-status" style="padding-left: 10px;"> 操作</div>
                    </div>
                    <div class="upload-view-body">
                        <uploader-list></uploader-list>
                    </div>
                </div>
            </div>

        </uploader>
    </div>
</template>

<script>
    import ApiUrl from '../../../config/api'
    import uploaderList from './uploaderList'
    import SparkMD5 from 'spark-md5'
    import uploader from '../../Plugin/Uploader/Uploader'
    import { formatSize, getNotUploadFile, getFileType } from '../../../utils/utils'

    export default {
        name: "UploaderPlugn",
        components: {
            uploaderList,
            uploader
        },
        props: {
            opts: {
                type: Object,
                default() {
                    return {}
                }
            }
        },
        data() {
            return {
                options: {
                    target: ApiUrl.UploadApiUrl.upload,
                    chunkSize: 1*1024*1024,
                    fileParameterName: 'file',
                    forceChunkSize: true,
                    initialPaused: true,
                    maxChunkRetries: 3,
                    simultaneousUploads: 3,
                    testChunks: false,   //是否开启服务器分片校验
                    speedSmoothingFactor: 0.02,
                    testMethod: 'POST',
                    progressCallbacksInterval: 200,
                    method: 'octet',
                    allowDuplicateUploads : true,
                    // 服务器分片校验函数，秒传及断点续传基础
                    checkChunkUploadedByResponse: function (chunk, message) {
                        message = JSON.parse(message);
                        let ret = message.data;
                        if (ret.skipUpload) {
                            chunk.file.status = 'success';
                            chunk.file.statusText = '秒传';
                            chunk.file.statusCode = 20001;
                            chunk.file.file_path = chunk.file.savePath;
                            chunk.file.isrun = false;
                            chunk.file.run_type= '';
                            chunk.file.step = 'added';
                            chunk.file.is_task = false;
                            chunk.file.id = new Date().getTime();
                            console.log('秒传');
                            return true;
                        }
                        return (ret.uploaded || []).indexOf(chunk.offset + 1) >= 0
                    },
                    headers: {
                        Authorization: this.Bus.User.UserToken
                    },
                    query: {

                    }
                },
                fileList: [],
                panelShow: false,
                panelHideList: false,
                statusText: {
                    success: '上传完成',
                    error: '上传出错',
                    uploading: '正在上传',
                    paused: '暂停上传',
                    waiting: '等待上传'
                },
                uploadConfig: {},
                getConfigLoding: true,
                AllFileSize: 0,
                UploadedSize: 0,
                currTaskNum: 0
            }
        },
        methods: {
            refreshBatch() {
                this.$parent.refreshBatch();
            },
            onFileAdded(file,event) {
                file.isrun = false;
                file.run_type= '';
                file.step = 'pending';
                file.is_task = true;

                this.AllFileSize = this.uploader.getSize();
                this.AllFileSize = this.uploader.sizeUploaded();
                this.fileList = this.uploader.fileList;
                this.Bus.Uploader.UploaderDrag = false;
                file.is_reckon_md5 = false;
                file.reckon_md5_num = 0;
                file.status = 'pending';
                file.ext = file.getType();
                file.file_type = getFileType(file.getType());

                let dirId = typeof this.$route.params.dir_id == "undefined" ? '/':this.$route.params.dir_id;
                file.savePath = dirId;
                if(typeof this.uploadConfig.max_file_size != 'undefined' && this.uploadConfig.max_file_size > 0 && file.size > this.uploadConfig.max_file_size) {
                    file.status = 'error';
                    file.statusCode = 411;
                    file.statusStrTitle = '超出'+formatSize(this.uploadConfig.max_file_size)+'限制';
                    file.error = true;
                    file.isrun = false;
                    file.run_type= '';
                    file.step = 'error';
                    file.is_task = false;
                    // file.ignored = true;
                } else if(typeof this.uploadConfig.zone_size != 'undefined' && file.size > this.uploadConfig.zone_size) {
                    file.status = 'error';
                    file.statusCode = 411;
                    file.statusStrTitle = '空间不足';
                    file.error = true;
                    file.isrun = false;
                    file.run_type= '';
                    file.step = 'error';
                    file.is_task = false;
                } else {
                    this.uploadNext();
                }
                // this.computeMD5(file);
            },
            uploadNext() {
                if(this.currTaskNum >= this.uploadConfig.max){
                    let getFile = getNotUploadFile(fileList, this.currTaskNum > 0 ? this.uploadConfig.max - this.currTaskNum : this.uploadConfig.max);
                    console.log(this.currTaskNum , this.uploadConfig.max);
                    console.log(getFile,fileList);
                    return false;
                }
                let fileList = this.uploader.fileList;
                let getFile = getNotUploadFile(fileList, this.currTaskNum > 0 ? this.uploadConfig.max - this.currTaskNum : this.uploadConfig.max);
                let ActFile = getFile.ActFile;
                this.currTaskNum = getFile.ActLen;
                if(ActFile.length < 1) {
                    // 文件全部上传完成
                } else {
                    for (var file of ActFile) {
                        let step = file.step;

                        // 判断文件夹是否存在并且检测用户空间
                        this.$ajax.post(ApiUrl.UploadApiUrl.check_zone, {
                            fileName: file.name,
                            filesize: file.size,
                            pdir: file.savePath,
                            save_path: file.relativePath,
                            ...this.params,
                        }, {}).then(function (ret) {
                            let dataS = ret.data;
                            let code = dataS.code;
                            let data = dataS.data;
                            if (code == 200) {
                                if(step == 'pending') {
                                    this.computeMD5(file);
                                } else if(step == 'uploading') {
                                    file.resume();
                                }
                                this.uploadNext();
                                this.$parent.refreshBatch();
                            } else {
                                if(code == 411) {
                                    file.status = 'error';
                                    file.statusCode = 411;
                                    file.statusStrTitle = '空间不足';
                                    file.error = true;
                                    file.isrun = false;
                                    file.run_type= '';
                                    file.step = 'error';
                                    file.is_task = false;
                                } else if(code == 412) {
                                    file.status = 'error';
                                    file.statusCode = 412;
                                    file.statusStrTitle = '文件夹不存在';
                                    file.error = true;
                                    file.isrun = false;
                                    file.run_type= '';
                                    file.step = 'error';
                                    file.is_task = false;
                                } else if(code == 403) {
                                    file.status = 'error';
                                    file.statusCode = 403;
                                    file.statusStrTitle = '文件夹不存在';
                                    file.error = true;
                                    file.isrun = false;
                                    file.run_type= '';
                                    file.step = 'error';
                                    file.is_task = false;
                                } else if(code == 500) {
                                    file.status = 'error';
                                    file.statusCode = 403;
                                    file.statusStrTitle = '文件夹创建失败';
                                    file.error = true;
                                    file.isrun = false;
                                    file.run_type= '';
                                    file.step = 'error';
                                    file.is_task = true;
                                }
                            }
                        }.bind(this));

                    }
                }
            },
            onFileProgress(rootFile, file, chunk) {
                this.UploadedSize = this.uploader.sizeUploaded();
                this.AllFileSize = this.uploader.getSize();
                // console.log(`上传中 ${file.name}，chunk：${chunk.startByte / 1024 / 1024} ~ ${chunk.endByte / 1024 / 1024}`)
            },
            onFileSuccess(rootFile, file, response, chunk) {
                let res = JSON.parse(response);
                if (!res.data) {
                    this.$message.error(res.message);
                    this.setTaskDec();
                    return
                }
                // 如果服务端返回需要合并
                if (res.data.needMerge) {
                    file.status = 'merge';
                    file.statusText = '正在效验';
                    this.$ajax.post(ApiUrl.UploadApiUrl.merge, {
                        tempName: res.tempName,
                        fileName: file.name,
                        md5: file.uniqueIdentifier,
                        pdir: file.savePath,
                        fileSize: file.size,
                        save_path: file.relativePath,
                        ...this.params,
                    }, {}).then(function (ret) {
                        let dataS = ret.data;
                        let data = dataS.data;
                        if (dataS.code == 200) {
                            file.status = 'success';
                            file.statusText = '上传成功';
                            file.file_path = data.file_path;
                            this.Bus.Batch.zone = data.zone;
                            this.Bus.Batch.use_zone = data.use_zone;
                            file.isrun = false;
                            file.run_type= 'success';
                            file.step = '';
                            file.is_task = false;
                        } else {
                            file.isrun = false;
                            file.run_type= 'success';
                            file.step = '';
                            file.is_task = false;
                            file.status = 'error';
                            file.statusText = '上传失败';
                        }
                        file.id = new Date().getTime();
                        this.setTaskDec();
                    }.bind(this));
                    return;
                    // 不需要合并
                } else {
                    file.isrun = false;
                    file.run_type= 'success';
                    file.step = '';
                    file.is_task = false;
                    file.is_task = false;
                    file.id = new Date().getTime();
                    this.setTaskDec();
                }
            },
            onFileComplete(file) {
                file.isrun = false;
                file.run_type= 'success';
                file.step = '';
                file.is_task = false;
                file.is_task = false;
                file.id = new Date().getTime();
                this.setTaskDec();
            },
            onFileError(rootFile, file, response, chunk) {
                file.isrun = false;
                file.run_type= 'error';
                file.step = 'uploading';
                file.is_task = false;
                file.is_task = false;
                file.id = new Date().getTime();
                this.setTaskDec();
            },
            /**
             * 计算md5，实现断点续传及秒传
             * @param file
             */
            computeMD5(uoloadFile) {
                let md5 = '';
                uoloadFile.pause();
                uoloadFile.status = 'reckon_md5';
                uoloadFile.isrun = true;
                uoloadFile.run_type= 'reckon_md5';
                uoloadFile.step = 'reckon_md5';
                uoloadFile.is_task = true;
                uoloadFile.reckon_md5_num = 0;

                var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
                    chunkSize = this.options.chunkSize, // read in chunks of 2MB
                    chunks = Math.ceil(uoloadFile.size / chunkSize),
                    currentChunk = 0,
                    spark = new SparkMD5.ArrayBuffer(),
                    frOnload = function(e){
                        spark.append(e.target.result); // append array buffer
                        currentChunk++;
                        let reckon_md5_num = Math.floor(currentChunk / chunks * 100);
                        if(uoloadFile.reckon_md5_num != reckon_md5_num) {
                            uoloadFile.reckon_md5_num = reckon_md5_num;
                            uoloadFile.md5_num = reckon_md5_num;
                            uoloadFile.id = new Date().getTime();
                        }
                        if (currentChunk < chunks){
                            loadNext();
                        } else {
                            md5 = spark.end();
                            this.uploader.opts.query = {
                                ...this.params
                            }
                            uoloadFile.is_reckon_md5 = true;
                            uoloadFile.uniqueIdentifier = md5;
                            uoloadFile.status = 'uploading';
                            uoloadFile.isrun = false;
                            uoloadFile.run_type= 'uploading';
                            uoloadFile.step = 'uploading';
                            uoloadFile.is_task = true;
                            uoloadFile.resume();
                        }
                    }.bind(this),
                    frOnerror = function () {
                        console.warn('oops, something went wrong.');
                    };
                function loadNext() {
                    var fileReader = new FileReader();
                    fileReader.onload = frOnload;
                    fileReader.onerror = frOnerror;
                    var start = currentChunk * chunkSize,
                        end = ((start + chunkSize) >= uoloadFile.file.size) ? uoloadFile.file.size : start + chunkSize;
                    fileReader.readAsArrayBuffer(blobSlice.call(uoloadFile.file, start, end));
                };
                loadNext();
            },
            close() {
                this.uploader.cancel();
                this.panelShow = false;
            },
            error(msg) {
                this.$notify({
                    title: this.$t('c.false'),
                    message: msg,
                    type: 'error',
                    duration: 2000
                })
            },
            hideDrag(e) {
                this.Bus.Uploader.UploaderDrag = (e.clientX > 0 && e.clientY > 0) === true ? true : false;
            },
            showDrag(e) {
                this.Bus.Uploader.UploaderDrag = true;
            },
            setTaskInc() {

            },
            setTaskDec() {
                this.currTaskNum--;
                this.$parent.refreshBatch();
                this.uploadNext();
            }
        },
        computed: {
            //Uploader实例
            uploader() {
                let uploader = this.$refs.uploader.uploader;
                uploader.assignDrop(document.getElementById('app'));
                return uploader;
            },
        },
        watch: {
            fileList(newVal, oldVal) {
                if(newVal.length > 0) {
                    this.panelShow = true;
                } else {
                    this.panelShow = false;
                }
            },
        },
        mounted: function () {
            this.$nextTick(function () {
                this.$emit('set-ref-uploader',this.uploader);
                this.Bus.Uploader.Uploader = this.uploader;
                this.fileList = this.uploader.fileList;
            })
        },
        created() {
            let opts = this.opts;
            this.options.target = opts.target;
            this.options.chunkSize = opts.chunkSize;
            this.options.simultaneousUploads = opts.simultaneousUploads;
            if(typeof opts.headers != 'undefined' && opts.headers != {}) {
                this.options.headers = Object.assign(this.options.headers,opts.headers);
            }
            this.options.query = Object.assign(this.options.query,opts.query);
            this.uploadConfig = opts.uploadConfig;
        }
    }
</script>

<style scoped lang="less">
    /*@import "../../../assets/css/upload.less";*/
</style>

<style lang="less">
    @import "../../../assets/css/upload.less";
    .Uploader.file-upload-wrap {
        visibility: hidden ;
    }
    .Uploader.file-upload-wrap.show {
        visibility:visible;
    }
</style>